package caramcraft;

import java.util.LinkedList;

import jnibwapi.BWAPIEventListener;
import jnibwapi.JNIBWAPI;
import jnibwapi.model.Unit;
import jnibwapi.types.UnitType;

/**
 * Created by Stefan Rudolph on 17.02.14.
 */
public class caramcraftAI implements BWAPIEventListener, Runnable {

	private final JNIBWAPI bwapi;
	private long frame;

	private LinkedList<Unit> myBuildings = new LinkedList<Unit>();
	private LinkedList<SCUnit> myUnits = new LinkedList<SCUnit>();

	private LinkedList<Unit> enemyBuildings = new LinkedList<Unit>();
	private LinkedList<SCUnit> enemyUnits = new LinkedList<SCUnit>();

	private final int marineID = UnitType.UnitTypes.Terran_Marine.getID();
	private final int vultureID = UnitType.UnitTypes.Terran_Vulture.getID();
	private final int medicID = UnitType.UnitTypes.Terran_Medic.getID();
	private final int tankID = UnitType.UnitTypes.Terran_Siege_Tank_Tank_Mode
			.getID();
	
	private int marineId = 0;
	private int vultureId = 0;

	public caramcraftAI() {
		System.out.println("This is CaramCraft!");
		bwapi = new JNIBWAPI(this, false);
	}

	public static void main(String[] args) {
		(new caramcraftAI()).run();
	}

	@Override
	public void matchStart() {
		myUnits.clear();
		myBuildings.clear();
		
		enemyUnits.clear();
		enemyBuildings.clear();
		
		marineId = 0;
		vultureId = 0;
		
		frame = 0;

		bwapi.enablePerfectInformation();
		bwapi.enableUserInput();
		bwapi.setGameSpeed(4);

		bwapi.drawHealth(true);
		bwapi.drawTargets(true);
	}

	@Override
	public void matchFrame() {
		for (SCUnit unit : this.myUnits) {
			unit.step(frame);
		}

		if (frame % 1000 == 0) {
			System.out.println("Frame: " + frame);
		}
		frame++;
	}

	@Override
	public void unitDiscover(int unitID) {
		Unit unit = bwapi.getUnit(unitID);
		int typeID = unit.getTypeID();
		boolean myUnit = unit.getPlayerID() == bwapi.getSelf().getID();
		if (!myUnit) {
			if (typeID == this.marineID)
				this.enemyUnits.add(new Marine(unit, bwapi));
			else if (typeID == medicID)
				this.enemyUnits.add(new Medic(unit, bwapi));
			else if (typeID == vultureID)
				this.enemyUnits.add(new Vulture(unit, bwapi));
			else if (typeID == tankID)
				this.enemyUnits.add(new Tank(unit, bwapi));
			else
				this.enemyBuildings.add(unit);
		} else {
			if (typeID == this.marineID)
			{
				this.myUnits.add(new Marine(unit, bwapi, myUnits, myBuildings,
						enemyUnits, enemyBuildings, marineId));
				marineId++;
			}
			else if (typeID == medicID)
				this.myUnits.add(new Medic(unit, bwapi, myUnits, myBuildings,
						enemyUnits, enemyBuildings));
			else if (typeID == vultureID)
			{
				this.myUnits.add(new Vulture(unit, bwapi, myUnits, myBuildings,
						enemyUnits, enemyBuildings, vultureId));
				vultureId++;
			}
			else if (typeID == tankID)
				this.myUnits.add(new Tank(unit, bwapi, myUnits, myBuildings,
						enemyUnits, enemyBuildings));
			else
				this.myBuildings.add(unit);
		}
	}

	@Override
	public void unitDestroy(int unitID) {
		for (Unit u : this.myBuildings) {
			if (u.getID() == unitID) {
				this.myBuildings.remove(u);
				return;
			}
		}
		for (Unit u : this.enemyBuildings) {
			if (u.getID() == unitID) {
				this.enemyBuildings.remove(u);
				return;
			}
		}
		for (SCUnit u : this.myUnits) {
			if (u.getID() == unitID) {
				this.myUnits.remove(u);
				return;
			}
		}

		for (SCUnit u : this.enemyUnits) {
			if (u.getID() == unitID) {
				this.enemyUnits.remove(u);
				return;
			}
		}
	}

	@Override
	public void connected() {
		System.out.println("Caramcraft connected.");
	}

	@Override
	public void matchEnd(boolean winner) {
		System.out.println(winner ? "We won!" : "Next time, we win!");
	}

	@Override
	public void keyPressed(int keyCode) {

	}

	@Override
	public void sendText(String text) {

	}

	@Override
	public void receiveText(String text) {

	}

	@Override
	public void playerLeft(int playerID) {

	}

	@Override
	public void nukeDetect(int x, int y) {

	}

	@Override
	public void nukeDetect() {

	}

	@Override
	public void unitEvade(int unitID) {

	}

	@Override
	public void unitShow(int unitID) {

	}

	@Override
	public void unitHide(int unitID) {

	}

	@Override
	public void unitCreate(int unitID) {
	}

	@Override
	public void unitMorph(int unitID) {

	}

	@Override
	public void unitRenegade(int unitID) {

	}

	@Override
	public void saveGame(String gameName) {

	}

	@Override
	public void unitComplete(int unitID) {

	}

	@Override
	public void playerDropped(int playerID) {

	}

	@Override
	public void run() {
		bwapi.start();
	}
}
